import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage, ElMessageBox } from "element-plus";
import { refreshToken } from '../api/user'
import { useUserStore } from "../store/modules/user"
import router from "../router/index"
import * as  _ from 'lodash'
import { closeWebSocket } from '../utils/socket';
let isRefreshing = false
let refreshSubscribers = []
// 过期提醒
var returnTip = _.debounce((tip) => {
    closeWebSocket()
    ElMessageBox.confirm(tip, '温馨提示', {
        confirmButtonText: '确定',
        type: 'error',
        showCancelButton: false,
        showClose: false,
        closeOnClickModal: false,
        closeOnPressEscape: false,
    })
        .then(() => {
            window.localStorage.removeItem('ddfUserStat')
            const UserStore = useUserStore()
            UserStore.token = null
            UserStore.roles = []
            UserStore.row = {
                tokenValue: null,//登录token
                expireIn: null,//过期时间   
                tokenStartTime: null,//登录当前时间
                refreshToken: null,//刷新token
                tokenName: null,
            }
            router.push({ path: '/login/index' })
        })
},800,{leading:false})

// 创建axios实例 进行基本参数配置
const service = axios.create({
    // 默认请求地址，根据环境的不同可在.env 文件中进行修改
    // baseURL: import.meta.env.VUE_APP_BASE_API,
    baseURL: import.meta.env.VITE_APP_BASE_API,
    // 设置接口访问超时时间
    timeout: 300000, // request timeout，
    // 跨域时候允许携带凭证
    withCredentials: true
})

//  request interceptor 接口请求拦截
service.interceptors.request.use((config: AxiosRequestConfig) => {
    const UserStore = useUserStore()
    /**
     * 用户登录之后获取服务端返回的token,后面每次请求都在请求头中带上token进行JWT校验
     * token 存储在本地储存中（storage）、vuex、pinia
     */
    // let token = UserStore.token
    let token = UserStore.row.tokenValue
    // config.headers[UserStore.row.tokenName] = token
    /**
       * 判断是否刷新token，如果为正在刷新token，且请求为刷新token的路径，则直接放行
       */
    if (isRefreshing && config.url == '/login/refreshToken') {
        return config;
    }

    // 获取存储token的开始时间
    const tokenStartTime = UserStore.row.tokenStartTime
    // 后台给出的token有效时间，一个星期 单位 是秒
    const timeOver = UserStore.row.expireIn * 1000
    // 当前时间
    let date = new Date().getTime()
    if (token) {
        //15分钟内刷新token
        if (date - tokenStartTime > timeOver - 15 * 60 * 1000 && date - tokenStartTime < timeOver) {
            if (!isRefreshing) {
                isRefreshing = true
                refreshToken({ refreshToken: UserStore.row.refreshToken }).then(res => {
                    UserStore.token = res.data.data.row.tokenValue
                    UserStore.row = { ...res.data.data.row, tokenStartTime: new Date().getTime() }
                    refreshSubscribers.forEach((cb) => cb(res.data.data.row.tokenValue))
                    refreshSubscribers = []
                    isRefreshing = false
                })
            }
            // 返回未执行 resolve 的Promise
            const retryOriginalRequest = new Promise(resolve => {
                // 用函数形式 将resolve 存入，等待刷新后再执行
                refreshSubscribers.push(token => {
                    config.headers[UserStore.row.tokenName] = token
                    resolve(config)
                })
            })

            // 返回config，继续原始请求
            return retryOriginalRequest

        }
        // 如果大于说明是token过期了
        if (date - tokenStartTime > timeOver) {
            returnTip('登录状态过期，请重新登录')
            return Promise.reject()
        }
        return config
    }
    return config
}, (error: AxiosError) => {
    // 请求错误，这里可以用全局提示框进行提示
    ElMessage({
        message: '服务器处理繁忙，请稍后重试！',
        type: 'error',
        duration: 3000,
    })
    return Promise.reject(error);
})

//  response interceptor 接口响应拦截
service.interceptors.response.use((response: AxiosResponse) => {
    // 错误提醒
    if (response.data.code == 40100||response.data.code == 41000) {
        returnTip(response.data.message)
        return response
      } else if (response.data.code == 40101) {
        returnTip(response.data.message)
        return response
      } else if (response.data.code == 40102) {
        returnTip(response.data.message)
        return response
      } else {
        return response
      }
    // 直接返回res，当然你也可以只返回res.data
    // 系统如果有自定义code也可以在这里处理

}, (error: AxiosError) => {
    // 处理响应错误，比如根据状态码进行不同的操作
    ElMessage({
        message: '服务器处理繁忙，请稍后重试！',
        type: 'error',
        duration: 3000,
    })
    return Promise.reject(error)
})

/**
 * @description 显示错误消息
 * opt 传入参数
 * err 错误信息
 * type 消息类型
 * duration 消息持续时间
 */
function showErrMessage(opt, err, type: any = 'error', duration: number = 5000) {
    ElMessage({
        message: err.msg,
        type: type,
        duration: duration
    })
}

export default service
